Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | export const dynamic = 'force-dynamic' import {getServerSession} from 'next-auth' import {notFound, redirect} from 'next/navigation' import {authOptions} from '@/lib/auth' import {pageSession} from '@/lib/guard' import {followToBand} from '@/lib/band' import {getSetlist} from '@/lib/setlists' import Perform, {type PerformSong} from '@/components/Perform' import {myCues} from '@/lib/cues-server' import SaveOffline from '@/components/pwa/SaveOffline' import {formatClock, runningOrder} from '@/lib/gig' export const metadata = {title: 'Perform'} export default async function PerformPage({params}: {params: {id: string}}) { const session = await getServerSession(authOptions) if (!session?.user) redirect( '/login?callbackUrl=' + encodeURIComponent(`/perform/${params.id}`), ) const {user, band} = await pageSession() const set = await getSetlist(params.id, band.id) if (!set) { await followToBand('setlist', params.id, user.id, `/perform/${params.id}`) notFound() } // Every chart in the set is sent with the page, so once it has loaded the // whole set works without a connection. const {entries, sets, divided} = runningOrder(set.startTime, set.items) const cues = await myCues( user.id, set.items.flatMap((i) => (i.songId ? [i.songId] : [])), ) const songs: PerformSong[] = [] entries.forEach((e, at) => { if (e.kind !== 'SONG' || !e.item.song) return const s = e.item.song // What comes between this song and the next one: a break, or a new set const brk = entries.slice(at + 1).findIndex((x) => x.kind === 'SONG') const gap = entries.slice(at + 1, brk < 0 ? undefined : at + 1 + brk) const pause = gap.find((x) => x.kind === 'BREAK') const nextSet = gap.find((x) => x.kind === 'SET') songs.push({ id: s.id, title: s.title, leadSinger: s.leadSinger, source: s.chartVersions[0]?.source ?? '', key: e.item.key, note: e.item.note, cues: cues.get(s.id) ?? [], set: divided ? {label: sets[e.set].label, n: e.n, count: sets[e.set].songs} : null, after: pause?.kind === 'BREAK' ? { kind: 'break', minutes: pause.info.minutes, until: pause.info.end != null ? formatClock(pause.info.end) : null, } : nextSet?.kind === 'SET' && brk >= 0 ? {kind: 'set', label: nextSet.info.label} : null, }) }) return ( <> <Perform setId={set.id} name={set.name} songs={songs} /> {/* The setlist and its charts too, as opening the setlist does */} <SaveOffline quiet urls={[ `/setlists/${set.id}`, ...new Set( set.items.flatMap((i) => (i.songId ? [`/songs/${i.songId}`] : [])), ), ]} /> </> ) } |